home *** CD-ROM | disk | FTP | other *** search
/ OpenGL Superbible (2nd Edition) / OpenGL SuperBible e2.iso / tools / Mesa-3.0 / SRC / MISC.C < prev    next >
Encoding:
C/C++ Source or Header  |  1998-09-18  |  14.4 KB  |  495 lines

  1. /* $Id: misc.c,v 3.14 1998/09/18 02:32:02 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  3.0
  6.  * Copyright (C) 1995-1998  Brian Paul
  7.  *
  8.  * This library is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Library General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2 of the License, or (at your option) any later version.
  12.  *
  13.  * This library is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Library General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Library General Public
  19.  * License along with this library; if not, write to the Free
  20.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23.  
  24. /*
  25.  * $Log: misc.c,v $
  26.  * Revision 3.14  1998/09/18 02:32:02  brianp
  27.  * fixed alpha clear problem reported by Sam Jordan
  28.  *
  29.  * Revision 3.13  1998/07/18 03:33:53  brianp
  30.  * glRead/DrawBuffer() generated GL_INVALID_ENUM instead of GL_INVALID_OPERATION
  31.  *
  32.  * Revision 3.12  1998/06/19 02:37:58  brianp
  33.  * fixed an error code in glReadBuffer()
  34.  *
  35.  * Revision 3.11  1998/06/07 22:18:52  brianp
  36.  * implemented GL_EXT_multitexture extension
  37.  *
  38.  * Revision 3.10  1998/04/22 00:52:42  brianp
  39.  * added GLcontext parameter to driver ExtensionString()
  40.  *
  41.  * Revision 3.9  1998/04/14 00:02:10  brianp
  42.  * fixed bug in which whole buffer might be cleared instead of scissor rect
  43.  *
  44.  * Revision 3.8  1998/03/27 04:39:44  brianp
  45.  * Driver.ExtensionString() must now return complete extension list
  46.  *
  47.  * Revision 3.7  1998/03/19 02:04:22  brianp
  48.  * added GL_SGIS_texture_edge_clamp
  49.  *
  50.  * Revision 3.6  1998/03/15 18:50:25  brianp
  51.  * added GL_EXT_abgr extension
  52.  *
  53.  * Revision 3.5  1998/03/15 18:32:12  brianp
  54.  * applied DavidB's patches for v0.23 of fxmesa driver
  55.  *
  56.  * Revision 3.4  1998/02/20 04:50:44  brianp
  57.  * implemented GL_SGIS_multitexture
  58.  *
  59.  * Revision 3.3  1998/02/01 16:37:19  brianp
  60.  * added GL_EXT_rescale_normal extension
  61.  *
  62.  * Revision 3.2  1998/02/01 15:23:52  brianp
  63.  * added ExtensionString() function to device driver
  64.  *
  65.  * Revision 3.1  1998/01/31 23:58:19  brianp
  66.  * new gl_Clear: removed ClearDepthBuffer and ClearColorAndDepth functions
  67.  *
  68.  * Revision 3.0  1998/01/31 20:59:27  brianp
  69.  * initial rev
  70.  *
  71.  */
  72.  
  73.  
  74. #ifdef PC_HEADER
  75. #include "all.h"
  76. #else
  77. #include <stdlib.h>
  78. #include <string.h>
  79. #include "accum.h"
  80. #include "alphabuf.h"
  81. #include "context.h"
  82. #include "depth.h"
  83. #include "macros.h"
  84. #include "masking.h"
  85. #include "misc.h"
  86. #include "stencil.h"
  87. #include "types.h"
  88. #endif
  89.  
  90.  
  91.  
  92. void gl_ClearIndex( GLcontext *ctx, GLfloat c )
  93. {
  94.    if (INSIDE_BEGIN_END(ctx)) {
  95.       gl_error( ctx, GL_INVALID_OPERATION, "glClearIndex" );
  96.       return;
  97.    }
  98.    ctx->Color.ClearIndex = (GLuint) c;
  99.    if (!ctx->Visual->RGBAflag) {
  100.       /* it's OK to call glClearIndex in RGBA mode but it should be a NOP */
  101.       (*ctx->Driver.ClearIndex)( ctx, ctx->Color.ClearIndex );
  102.    }
  103. }
  104.  
  105.  
  106.  
  107. void gl_ClearColor( GLcontext *ctx, GLclampf red, GLclampf green,
  108.                     GLclampf blue, GLclampf alpha )
  109. {
  110.    if (INSIDE_BEGIN_END(ctx)) {
  111.       gl_error( ctx, GL_INVALID_OPERATION, "glClearColor" );
  112.       return;
  113.    }
  114.  
  115.    ctx->Color.ClearColor[0] = CLAMP( red,   0.0F, 1.0F );
  116.    ctx->Color.ClearColor[1] = CLAMP( green, 0.0F, 1.0F );
  117.    ctx->Color.ClearColor[2] = CLAMP( blue,  0.0F, 1.0F );
  118.    ctx->Color.ClearColor[3] = CLAMP( alpha, 0.0F, 1.0F );
  119.  
  120.    if (ctx->Visual->RGBAflag) {
  121.       GLubyte r = (GLint) (ctx->Color.ClearColor[0] * 255.0F);
  122.       GLubyte g = (GLint) (ctx->Color.ClearColor[1] * 255.0F);
  123.       GLubyte b = (GLint) (ctx->Color.ClearColor[2] * 255.0F);
  124.       GLubyte a = (GLint) (ctx->Color.ClearColor[3] * 255.0F);
  125.       (*ctx->Driver.ClearColor)( ctx, r, g, b, a );
  126.    }
  127. }
  128.  
  129.  
  130.  
  131.  
  132. /*
  133.  * Clear the color buffer when glColorMask or glIndexMask is in effect.
  134.  */
  135. static void clear_color_buffer_with_masking( GLcontext *ctx )
  136. {
  137.    GLint x, y, height, width;
  138.  
  139.    /* Compute region to clear */
  140.    if (ctx->Scissor.Enabled) {
  141.       x = ctx->Buffer->Xmin;
  142.       y = ctx->Buffer->Ymin;
  143.       height = ctx->Buffer->Ymax - ctx->Buffer->Ymin + 1;
  144.       width  = ctx->Buffer->Xmax - ctx->Buffer->Xmin + 1;
  145.    }
  146.    else {
  147.       x = 0;
  148.       y = 0;
  149.       height = ctx->Buffer->Height;
  150.       width  = ctx->Buffer->Width;
  151.    }
  152.  
  153.    if (ctx->Visual->RGBAflag) {
  154.       /* RGBA mode */
  155.       GLubyte r = (GLint) (ctx->Color.ClearColor[0] * 255.0F);
  156.       GLubyte g = (GLint) (ctx->Color.ClearColor[1] * 255.0F);
  157.       GLubyte b = (GLint) (ctx->Color.ClearColor[2] * 255.0F);
  158.       GLubyte a = (GLint) (ctx->Color.ClearColor[3] * 255.0F);
  159.       GLint i;
  160.       for (i=0;i<height;i++,y++) {
  161.          GLubyte rgba[MAX_WIDTH][4];
  162.          GLint j;
  163.          for (j=0; j<width; j++) {
  164.             rgba[j][RCOMP] = r;
  165.             rgba[j][GCOMP] = g;
  166.             rgba[j][BCOMP] = b;
  167.             rgba[j][ACOMP] = a;
  168.          }
  169.          gl_mask_rgba_span( ctx, width, x, y, rgba );
  170.          (*ctx->Driver.WriteRGBASpan)( ctx, width, x, y, rgba, NULL );
  171.          if (ctx->RasterMask & ALPHABUF_BIT) {
  172.             gl_write_alpha_span( ctx, width, x, y, rgba, NULL );
  173.          }
  174.       }
  175.    }
  176.    else {
  177.       /* Color index mode */
  178.       GLuint indx[MAX_WIDTH];
  179.       GLubyte mask[MAX_WIDTH];
  180.       GLint i, j;
  181.       MEMSET( mask, 1, width );
  182.       for (i=0;i<height;i++,y++) {
  183.          for (j=0;j<width;j++) {
  184.             indx[j] = ctx->Color.ClearIndex;
  185.          }
  186.          gl_mask_index_span( ctx, width, x, y, indx );
  187.          (*ctx->Driver.WriteCI32Span)( ctx, width, x, y, indx, mask );
  188.       }
  189.    }
  190. }
  191.  
  192.  
  193.  
  194. /*
  195.  * Clear the front and/or back color buffers.  Also clear the alpha
  196.  * buffer(s) if present.
  197.  */
  198. static void clear_color_buffers( GLcontext *ctx )
  199. {
  200.    if (ctx->Color.SWmasking) {
  201.       clear_color_buffer_with_masking( ctx );
  202.    }
  203.    else {
  204.       GLint x = ctx->Buffer->Xmin;
  205.       GLint y = ctx->Buffer->Ymin;
  206.       GLint height = ctx->Buffer->Ymax - ctx->Buffer->Ymin + 1;
  207.       GLint width  = ctx->Buffer->Xmax - ctx->Buffer->Xmin + 1;
  208.       (void) (*ctx->Driver.Clear)( ctx, GL_COLOR_BUFFER_BIT,
  209.                                    !ctx->Scissor.Enabled,
  210.                                    x, y, width, height );
  211.       if (ctx->RasterMask & ALPHABUF_BIT) {
  212.          /* front and/or back alpha buffers will be cleared here */
  213.          gl_clear_alpha_buffers( ctx );
  214.       }
  215.    }
  216.  
  217.    if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
  218.       /*** Also clear the back buffer ***/
  219.       (*ctx->Driver.SetBuffer)( ctx, GL_BACK );
  220.       if (ctx->Color.SWmasking) {
  221.          clear_color_buffer_with_masking( ctx );
  222.       }
  223.       else {
  224.          GLint x = ctx->Buffer->Xmin;
  225.          GLint y = ctx->Buffer->Ymin;
  226.          GLint height = ctx->Buffer->Ymax - ctx->Buffer->Ymin + 1;
  227.          GLint width  = ctx->Buffer->Xmax - ctx->Buffer->Xmin + 1;
  228.          (void) (*ctx->Driver.Clear)( ctx, GL_COLOR_BUFFER_BIT,
  229.                                       !ctx->Scissor.Enabled,
  230.                                       x, y, width, height );
  231.       }
  232.       (*ctx->Driver.SetBuffer)( ctx, GL_FRONT );
  233.    }
  234. }
  235.  
  236.  
  237.  
  238. void gl_Clear( GLcontext *ctx, GLbitfield mask )
  239. {
  240. #ifdef PROFILE
  241.    GLdouble t0 = gl_time();
  242. #endif
  243.  
  244.    if (INSIDE_BEGIN_END(ctx)) {
  245.       gl_error( ctx, GL_INVALID_OPERATION, "glClear" );
  246.       return;
  247.    }
  248.  
  249.    if (ctx->RenderMode==GL_RENDER) {
  250.       GLint x, y, width, height;
  251.       GLbitfield newMask;
  252.  
  253.       if (ctx->NewState) {
  254.          gl_update_state( ctx );
  255.       }
  256.  
  257.       x = ctx->Buffer->Xmin;
  258.       y = ctx->Buffer->Ymin;
  259.       height = ctx->Buffer->Ymax - ctx->Buffer->Ymin + 1;
  260.       width  = ctx->Buffer->Xmax - ctx->Buffer->Xmin + 1;
  261.  
  262.       /* let device driver try to clear the buffers */
  263.       newMask = (*ctx->Driver.Clear)( ctx, mask, !ctx->Scissor.Enabled,
  264.                                       x, y, width, height );
  265.  
  266.       /* check if only clearing of alpha buffer needed */
  267.       if ( (mask & GL_COLOR_BUFFER_BIT) &&
  268.            (!(newMask & GL_COLOR_BUFFER_BIT)) &&
  269.            (ctx->RasterMask & ALPHABUF_BIT) )
  270.       {
  271.          gl_clear_alpha_buffers( ctx );
  272.       }
  273.  
  274.       if ((mask & GL_COLOR_BUFFER_BIT)
  275.           && ctx->RasterMask & FRONT_AND_BACK_BIT) {
  276.          /*** Also clear the back color buffer ***/
  277.          (*ctx->Driver.SetBuffer)( ctx, GL_BACK );
  278.          (void) (*ctx->Driver.Clear)( ctx, GL_COLOR_BUFFER_BIT,
  279.                                       !ctx->Scissor.Enabled,
  280.                                       x, y, width, height );
  281.          (*ctx->Driver.SetBuffer)( ctx, GL_FRONT );
  282.       }
  283.  
  284.       if (newMask & GL_COLOR_BUFFER_BIT)    clear_color_buffers( ctx );
  285.       if (newMask & GL_DEPTH_BUFFER_BIT)    gl_clear_depth_buffer( ctx );
  286.       if (newMask & GL_ACCUM_BUFFER_BIT)    gl_clear_accum_buffer( ctx );
  287.       if (newMask & GL_STENCIL_BUFFER_BIT)  gl_clear_stencil_buffer( ctx );
  288.  
  289. #ifdef PROFILE
  290.       ctx->ClearTime += gl_time() - t0;
  291.       ctx->ClearCount++;
  292. #endif
  293.    }
  294. }
  295.  
  296.  
  297.  
  298. const GLubyte *gl_GetString( GLcontext *ctx, GLenum name )
  299. {
  300.    static char result[1000];
  301.    static char *vendor = "Brian Paul";
  302.    static char *version = "1.2 Mesa 3.0";
  303.    static char *extensions = "GL_EXT_blend_color GL_EXT_blend_minmax GL_EXT_blend_logic_op GL_EXT_blend_subtract GL_EXT_paletted_texture GL_EXT_point_parameters GL_EXT_polygon_offset GL_EXT_vertex_array GL_EXT_texture_object GL_EXT_texture3D GL_MESA_window_pos GL_MESA_resize_buffers GL_EXT_shared_texture_palette GL_EXT_rescale_normal GL_EXT_abgr GL_SGIS_texture_edge_clamp GL_SGIS_multitexture GL_EXT_multitexture";
  304.  
  305.    if (INSIDE_BEGIN_END(ctx)) {
  306.       gl_error( ctx, GL_INVALID_OPERATION, "glGetString" );
  307.       return (GLubyte *) 0;
  308.    }
  309.  
  310.    switch (name) {
  311.       case GL_VENDOR:
  312.          return (GLubyte *) vendor;
  313.       case GL_RENDERER:
  314.          strcpy(result, "Mesa");
  315.          if (ctx->Driver.RendererString) {
  316.             strcat(result, " ");
  317.             strcat(result, (*ctx->Driver.RendererString)());
  318.          }
  319.          return (GLubyte *) result;
  320.       case GL_VERSION:
  321.          return (GLubyte *) version;
  322.       case GL_EXTENSIONS:
  323.          if (ctx->Driver.ExtensionString) {
  324.             /* driver specifies the extensions */
  325.             return (const GLubyte *) (*ctx->Driver.ExtensionString)(ctx);
  326.          }
  327.          else {
  328.             /* return default extensions */
  329.             return (const GLubyte *) extensions;
  330.          }
  331.       default:
  332.          gl_error( ctx, GL_INVALID_ENUM, "glGetString" );
  333.          return (GLubyte *) 0;
  334.    }
  335. }
  336.  
  337.  
  338.  
  339. void gl_Finish( GLcontext *ctx )
  340. {
  341.    /* Don't compile into display list */
  342.    if (INSIDE_BEGIN_END(ctx)) {
  343.       gl_error( ctx, GL_INVALID_OPERATION, "glFinish" );
  344.       return;
  345.    }
  346.    if (ctx->Driver.Finish) {
  347.       (*ctx->Driver.Finish)( ctx );
  348.    }
  349. }
  350.  
  351.  
  352.  
  353. void gl_Flush( GLcontext *ctx )
  354. {
  355.    /* Don't compile into display list */
  356.    if (INSIDE_BEGIN_END(ctx)) {
  357.       gl_error( ctx, GL_INVALID_OPERATION, "glFlush" );
  358.       return;
  359.    }
  360.    if (ctx->Driver.Flush) {
  361.       (*ctx->Driver.Flush)( ctx );
  362.    }
  363. }
  364.  
  365.  
  366.  
  367. void gl_Hint( GLcontext *ctx, GLenum target, GLenum mode )
  368. {
  369.    if (INSIDE_BEGIN_END(ctx)) {
  370.       gl_error( ctx, GL_INVALID_OPERATION, "glHint" );
  371.       return;
  372.    }
  373.    if (mode!=GL_DONT_CARE && mode!=GL_FASTEST && mode!=GL_NICEST) {
  374.       gl_error( ctx, GL_INVALID_ENUM, "glHint(mode)" );
  375.       return;
  376.    }
  377.    switch (target) {
  378.       case GL_FOG_HINT:
  379.          ctx->Hint.Fog = mode;
  380.          break;
  381.       case GL_LINE_SMOOTH_HINT:
  382.          ctx->Hint.LineSmooth = mode;
  383.          break;
  384.       case GL_PERSPECTIVE_CORRECTION_HINT:
  385.          ctx->Hint.PerspectiveCorrection = mode;
  386.          break;
  387.       case GL_POINT_SMOOTH_HINT:
  388.          ctx->Hint.PointSmooth = mode;
  389.          break;
  390.       case GL_POLYGON_SMOOTH_HINT:
  391.          ctx->Hint.PolygonSmooth = mode;
  392.          break;
  393.       default:
  394.          gl_error( ctx, GL_INVALID_ENUM, "glHint(target)" );
  395.    }
  396.    ctx->NewState |= NEW_ALL;   /* just to be safe */
  397. }
  398.  
  399.  
  400.  
  401. void gl_DrawBuffer( GLcontext *ctx, GLenum mode )
  402. {
  403.    if (INSIDE_BEGIN_END(ctx)) {
  404.       gl_error( ctx, GL_INVALID_OPERATION, "glDrawBuffer" );
  405.       return;
  406.    }
  407.    switch (mode) {
  408.       case GL_FRONT:
  409.       case GL_FRONT_LEFT:
  410.       case GL_FRONT_AND_BACK:
  411.          if ( (*ctx->Driver.SetBuffer)( ctx, GL_FRONT ) == GL_FALSE ) {
  412.             gl_error( ctx, GL_INVALID_OPERATION, "glDrawBuffer" );
  413.             return;
  414.          }
  415.          ctx->Color.DrawBuffer = mode;
  416.          ctx->Buffer->Alpha = ctx->Buffer->FrontAlpha;
  417.      ctx->NewState |= NEW_RASTER_OPS;
  418.          break;
  419.       case GL_BACK:
  420.       case GL_BACK_LEFT:
  421.          if ( (*ctx->Driver.SetBuffer)( ctx, GL_BACK ) == GL_FALSE) {
  422.             gl_error( ctx, GL_INVALID_OPERATION, "glDrawBuffer" );
  423.             return;
  424.          }
  425.          ctx->Color.DrawBuffer = mode;
  426.          ctx->Buffer->Alpha = ctx->Buffer->BackAlpha;
  427.      ctx->NewState |= NEW_RASTER_OPS;
  428.          break;
  429.       case GL_NONE:
  430.          ctx->Color.DrawBuffer = mode;
  431.          ctx->Buffer->Alpha = NULL;
  432.          ctx->NewState |= NEW_RASTER_OPS;
  433.          break;
  434.       case GL_FRONT_RIGHT:
  435.       case GL_BACK_RIGHT:
  436.       case GL_LEFT:
  437.       case GL_RIGHT:
  438.       case GL_AUX0:
  439.       case GL_AUX1:
  440.       case GL_AUX2:
  441.       case GL_AUX3:
  442.          gl_error( ctx, GL_INVALID_OPERATION, "glDrawBuffer" );
  443.          break;
  444.       default:
  445.          gl_error( ctx, GL_INVALID_ENUM, "glDrawBuffer" );
  446.    }
  447. }
  448.  
  449.  
  450.  
  451. void gl_ReadBuffer( GLcontext *ctx, GLenum mode )
  452. {
  453.    if (INSIDE_BEGIN_END(ctx)) {
  454.       gl_error( ctx, GL_INVALID_OPERATION, "glReadBuffer" );
  455.       return;
  456.    }
  457.    switch (mode) {
  458.       case GL_FRONT:
  459.       case GL_FRONT_LEFT:
  460.          if ( (*ctx->Driver.SetBuffer)( ctx, GL_FRONT ) == GL_FALSE) {
  461.             gl_error( ctx, GL_INVALID_OPERATION, "glReadBuffer" );
  462.             return;
  463.          }
  464.          ctx->Pixel.ReadBuffer = mode;
  465.          ctx->Buffer->Alpha = ctx->Buffer->FrontAlpha;
  466.          ctx->NewState |= NEW_RASTER_OPS;
  467.          break;
  468.       case GL_BACK:
  469.       case GL_BACK_LEFT:
  470.          if ( (*ctx->Driver.SetBuffer)( ctx, GL_BACK ) == GL_FALSE) {
  471.             gl_error( ctx, GL_INVALID_OPERATION, "glReadBuffer" );
  472.             return;
  473.          }
  474.          ctx->Pixel.ReadBuffer = mode;
  475.          ctx->Buffer->Alpha = ctx->Buffer->BackAlpha;
  476.          ctx->NewState |= NEW_RASTER_OPS;
  477.          break;
  478.       case GL_FRONT_RIGHT:
  479.       case GL_BACK_RIGHT:
  480.       case GL_LEFT:
  481.       case GL_RIGHT:
  482.       case GL_AUX0:
  483.       case GL_AUX1:
  484.       case GL_AUX2:
  485.       case GL_AUX3:
  486.          gl_error( ctx, GL_INVALID_OPERATION, "glReadBuffer" );
  487.          break;
  488.       default:
  489.          gl_error( ctx, GL_INVALID_ENUM, "glReadBuffer" );
  490.    }
  491.  
  492.    /* Remember, the draw buffer is the default state */
  493.    (void) (*ctx->Driver.SetBuffer)( ctx, ctx->Color.DrawBuffer );
  494. }
  495.